using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.DirectoryServices;

namespace ActAttrUI
{
    public partial class frmMain : Form
    {

        internal string strDomainDN;
        internal int numRecords;

        /// <summary>
        /// Struct to hold records loaded from the configuration file
        /// </summary>
        struct ConfigRecord
        {
            public string attribName;
            public string attribValue;
            public string attribType;
        };
        

        public frmMain()
        {
            InitializeComponent();
        }

        public void frmMain_Load(object sender, EventArgs e)
        {
            ConfigRecord[] cfgAttribs;

            try
            {
                cfgAttribs = LoadConfig("AttribEdit.cfg");
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while trying to open the configuration file.\n" + ex.Message);
                return;
            }
            
            BuildUI(cfgAttribs);            
        }

        /// <summary>
        /// LoadConfig loads the configuration of the UI from a file.  The format of the file should be as such: [Attribute Name],[Attribute Value Type]
        /// </summary>
        /// <param name="strFilename">The name of the file to be loaded.  The file path should match that of the executable path.</param>
        private ConfigRecord[] LoadConfig(string strFilename)
        {
            string strCurPath = Application.StartupPath;
            ConfigRecord[] tmpAttribs;

            try
            {
                using (StreamReader srConfig = new StreamReader(strCurPath + "\\" + strFilename))
                {

                    int cnt = 0;
                    string tmpStr;
                    tmpAttribs = new ConfigRecord[100];

                    while ((tmpStr = srConfig.ReadLine()) != null)
                    {
                        tmpAttribs[cnt].attribName = (tmpStr.Split(','))[0];
                        tmpAttribs[cnt].attribType = (tmpStr.Split(','))[1];
                        cnt++;
                    }
                    numRecords = cnt;
                }
            }
            catch
            {
                throw;
            }
            return tmpAttribs;

        }
        
        /// <summary>
        /// BuildUI will build the interface in real time to match the settings in the configuration file
        /// </summary>
        /// <param name="cfgAttributes">An array of ConfigRecord</param>
        void BuildUI(ConfigRecord[] cfgAttributes)
        {
            //ConfigRecord tmpRecord;
            int y = 1;
            int cnt = 0;

            for (cnt = 0; cnt <= numRecords - 1;cnt++)
            {
                ConfigRecord tmpRecord = cfgAttributes[cnt];
                Label tmpLabel = new Label();
                TextBox tmpTextBox = new TextBox();


                tmpLabel.Location = new Point(5, y * 25);
                tmpLabel.Text = tmpRecord.attribName + ":";
                toolTip1.SetToolTip(tmpLabel, "This attribute is of type " + tmpRecord.attribType);

                tmpTextBox.Location = new Point(tmpLabel.Width + 10, y * 25);
                tmpTextBox.Size = new Size(grpAttribs.Width - tmpLabel.Width - 25, 8);
                toolTip1.SetToolTip(tmpTextBox, "This attribute is of type " + tmpRecord.attribType);
                tmpTextBox.Name = tmpRecord.attribName;
                tmpTextBox.Text = tmpRecord.attribValue;

                grpAttribs.Controls.Add(tmpLabel);
                grpAttribs.Controls.Add(tmpTextBox);

                y++;
            }
            this.Height = y * 28 + 40;
            grpAttribs.Height = y * 28 + 6;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            strDomainDN = ConvertToLDAP(txtDomainFQDN.Text);

            if (strDomainDN.Length <= 0)
            {
                MessageBox.Show("Please enter a value for Domain.");
                return;
            }

            if (txtUsername.Text.Length <= 0)
            {
                MessageBox.Show("Please enter a value for Username.");
                return;
            }

            DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + strDomainDN);
            DirectorySearcher AD = new DirectorySearcher(searchRoot);
            DirectoryEntry tmpUser;

            try
            {
                AD.Filter = "(&(objectClass=user)(sAMAccountName= " + txtUsername.Text + "))";
                tmpUser = AD.FindOne().GetDirectoryEntry();
            }
            catch(Exception ex)
            {
                MessageBox.Show("An error occurred while trying to load data from the directory: \n" + ex.Message);
                return;
            }

            grpAttribs.Text = txtUsername + "'s Customer Attributes";

            foreach (Control tmpControl in grpAttribs.Controls)
            {
                if(tmpControl.GetType() == typeof(TextBox))
                {
                    try
                    {
                        tmpControl.Text = tmpUser.Properties[tmpControl.Name].Value.ToString();
                    }
                    catch(Exception ex)
                    {
                        //System.Runtime.InteropServices.COMException COMEx = (System.Runtime.InteropServices.COMException)ex;
                        MessageBox.Show(ex.Source.ToString() + ":  " + ex.Message);
                        //throw;
                    } //end Try
                } //end if
            } //end foreach
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdSave_Click(object sender, EventArgs e)
        {
            DirectoryEntry searchRoot = new DirectoryEntry("LDAP://" + strDomainDN);
            DirectorySearcher AD = new DirectorySearcher(searchRoot);
            DirectoryEntry tmpUser;

            try
            {
                AD.Filter = "(&(objectClass=user)(sAMAccountName= " + txtUsername.Text + "))";
                tmpUser = AD.FindOne().GetDirectoryEntry();
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occurred while trying to load data from the directory: \n" + ex.Message);
                return;
            }
            string strErrMsg = "";

            if (System.Windows.Forms.MessageBox.Show("Are you sure you'd like to submit the changes below?", "Submit", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                foreach (Control tmpControl in grpAttribs.Controls)
                {
                    if (tmpControl.GetType() == typeof(TextBox))
                    {
                        try
                        {
                            tmpUser.Properties[tmpControl.Name].Add(tmpControl.Text);
                            tmpUser.CommitChanges();
                        }
                        catch (Exception ex)
                        {
                            System.Runtime.InteropServices.COMException COMEx = (System.Runtime.InteropServices.COMException)ex;
                            strErrMsg += COMEx.ErrorCode.ToString() + ":  " + COMEx.Message + "\n";
                        } // End try
                    } // End if
                } // Next foreach
            } //End if

            if(strErrMsg.Length > 0)
            {
                strErrMsg = "An error occurred while attempting to save changes:\n\n" + strErrMsg;
            }
        } // End cmdSave_Click

        /// <summary>
        /// ConvertToLDAP takes the DNS Fully Qualified Domain Name and converts it into an X.500 format address
        /// </summary>
        /// <param name="fqdnDomain">String. Example: corp.contoso.com</param>
        /// <returns></returns>
        internal string ConvertToLDAP(string fqdnDomain)
        {
            string[] splitString = fqdnDomain.Split('.');
            string newString ="";

            foreach (string tmpStr in splitString)
            {
                newString += "DC=" + tmpStr + ",";
            }

            return newString.TrimEnd(',');
        }
    }
}